use std::time::Instant;
use std::{fs::File, time::Duration};
use std::io::Read;
use ratatui::text::{Line, Text};
use ratatui::{
    backend::CrosstermBackend,
    layout::{Constraint, Direction, Layout},
    style::{Modifier, Style},
    text::Span,
    widgets::{Block, Borders, Cell, Row, Table},
    Terminal,
};
use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use serde::Deserialize;
use crate::otp::{get_time_count, generate_totp};
use log::{info, error, debug};

#[derive(Debug, Deserialize)]
struct TOTPConfig {
    name: String,
    secret: String,
    expire_duration: u64,
    code_length: Option<usize>,
}

#[derive(Debug, Deserialize)]
struct Config {
    totps: Vec<TOTPConfig>,
}

fn load_config(path: &str) -> Result<Config, Box<dyn std::error::Error>> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    let config: Config = serde_yml::from_str(&contents)?;
    Ok(config)
}

pub fn run_tui(config_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    info!("启动 TUI 界面");

    // 设置终端
    enable_raw_mode()?;
    let mut stdout = std::io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    // 加载配置
    info!("正在加载配置文件: {}", config_path);
    let config = load_config(&config_path)?;
    debug!("加载的配置: {:?}", config);

    // 运行主循环
    info!("开始运行主循环");
    let res = run_app(&mut terminal, &config);

    // 恢复终端
    disable_raw_mode()?;
    execute!(
        terminal.backend_mut(),
        LeaveAlternateScreen,
        DisableMouseCapture
    )?;
    terminal.show_cursor()?;

    if let Err(err) = res {
        error!("运行过程中发生错误: {:?}", err);
        println!("{:?}", err)
    }

    info!("TUI 界面已关闭");
    Ok(())
}

fn run_app<B: ratatui::backend::Backend>(terminal: &mut Terminal<B>, config: &Config) -> Result<(), Box<dyn std::error::Error>> {
    let mut last_updates: Vec<Instant> = vec![Instant::now(); config.totps.len()];
    info!("开始主循环");
    let mut current_page = 0;
    let items_per_page = 60;
    let total_pages = (config.totps.len() + items_per_page - 1) / items_per_page;

    loop {
        let now = Instant::now();
        terminal.draw(|f| {
            let size = f.area();
            let chunks = Layout::default()
                .direction(Direction::Vertical)
                .margin(1)
                .constraints([Constraint::Percentage(100)].as_ref())
                .split(size);

            let start_index = current_page * items_per_page;
            let end_index = std::cmp::min(start_index + items_per_page, config.totps.len());

            let rows = config.totps[start_index..end_index].chunks(3).enumerate().map(|(chunk_index, chunk)| {
                let cells = chunk.iter().enumerate().map(|(index, totp)| {
                    let global_index = start_index + chunk_index * 3 + index;
                    let time_count = get_time_count(Some(totp.expire_duration));
                    let code = generate_totp(&totp.secret, time_count, totp.code_length);
                    let elapsed_time = now.duration_since(last_updates[global_index]).as_secs();
                    let remaining_time = totp.expire_duration - (elapsed_time % totp.expire_duration);
                    
                    let cell_content = vec![
                        Line::from(Span::styled(&totp.name, Style::default().add_modifier(Modifier::BOLD))),
                        Line::from(Span::raw(code)),
                        Line::from(Span::raw(format!("剩余时间: {}秒", remaining_time))),
                    ];
                    Cell::from(Text::from(cell_content))
                        .style(Style::default()
                        .bg(ratatui::style::Color::Reset)
                        .fg(ratatui::style::Color::Reset))
                }).collect::<Vec<_>>();
                Row::new(cells).height(3)
            }).collect::<Vec<_>>();

            let table = Table::new(rows, [Constraint::Percentage(33), Constraint::Percentage(33), Constraint::Percentage(33)])
                .block(Block::default().title(format!("二次验证码 (第 {} 页，共 {} 页)", current_page + 1, total_pages)).borders(Borders::ALL))
                .widths(&[
                    Constraint::Percentage(33), Constraint::Percentage(33), Constraint::Percentage(33)
                ])
                .column_spacing(1)
                .style(Style::default().bg(ratatui::style::Color::Reset).fg(ratatui::style::Color::Reset))
                .column_spacing(1)
                .style(Style::default().bg(ratatui::style::Color::Reset).fg(ratatui::style::Color::Reset));

            f.render_widget(table, chunks[0]);
        })?;
        for (index, last_update) in last_updates.iter_mut().enumerate() {
            if now.duration_since(*last_update).as_secs() >= config.totps[index].expire_duration {
                *last_update = now;
                debug!("更新 TOTP {}: {}", index, config.totps[index].name);
            }
        }

        if event::poll(Duration::from_millis(100))? {
            if let Event::Key(key) = event::read()? {
                match key.code {
                    KeyCode::Char('q') => {
                        info!("用户按下 'q' 键，退出程序");
                        return Ok(());
                    },
                    KeyCode::Left => {
                        if current_page > 0 {
                            current_page -= 1;
                            info!("用户翻到上一页，当前页码：{}", current_page + 1);
                        }
                    },
                    KeyCode::Right => {
                        if current_page < total_pages - 1 {
                            current_page += 1;
                            info!("用户翻到下一页，当前页码：{}", current_page + 1);
                        }
                    },
                    _ => {}
                }
            }
        }
    }
}